﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NCalculator.Operations
{
    [Serializable()]
    public class FibonacciNode : ValueNode
    {
        #region Attributes
        private int _n; // n-number of fibonacci
        #endregion

        public FibonacciNode()
        {
            _n = 0;
        }

        /// <summary>
        /// Expression number of fibonacci
        /// </summary>
        public int N
        {
            get { return _n; }
            set
            {
                if (value >= 0)
                    _n = value;
            }
        }

        /// <summary>
        /// Calculate n expression of fibonacci
        /// </summary>
        /// <param name="n">Number of expression to calculate</param>
        /// <returns>value of n-expression of fibonacci</returns>
        private double Fibonacci(int n)
        {
            if (n == 0)
                return 0;
            if (n <= 2)
                return 1;
            else
                return Fibonacci(n - 2) + Fibonacci(n - 1);
        }

        /// <summary>
        /// Iteration method for resolve fibonacci
        /// </summary>
        /// <param name="n">n-expression of fibonacci</param>
        /// <returns></returns>
        private double FibonacciIteration(int n)
        {
            if (n == 0) 
                return 0;
            if (n <= 2)
                return 1;
            else
            {
                double a = 1;
                double b = 1;
                double c = 0;
                for (int i = 0; i < n-2; i++)
                {
                    c = a + b;
                    a = b;
                    b = c;
                }
                return c;
            }
        }

        public override string ToString()
        {
            return string.Format("Fib({0}) ", _n);
        }

        /// <summary>
        /// Calculated n-expression of fibonacci
        /// </summary>
        /// <returns>fibonacci n-expression</returns>
        public override double Evaluation()
        {
            return FibonacciIteration(_n);
        }
    }
}
